package com.zmp.kotlinnote.coroutines

import com.zmp.kotlinnote.exchange.log
import kotlinx.coroutines.*
import org.junit.Test
import java.text.SimpleDateFormat

/**
 *@author zmp
 *Created by zmp on 2018/12/25
 *TODO
 */
class _XC_2 {
    @Test
    fun launch() {
        GlobalScope.launch {
            //开启一个后台协程
            repeat(3) {
                delay(1000)
                "repeat:$it".log()
            }
        }
        Thread.sleep(2500)   //阻塞主线程
        "main thread end".log()
        /**  打印结果
         *   _协程_2.kt:invokeSuspend:19->: repeat:0
         *   _协程_2.kt:invokeSuspend:19->: repeat:1
         *   _协程_2.kt:main:23->: main thread end
         */
    }

    @Test
    fun lazy() {
        //CoroutineStart.LAZY  不会开始执行
        val lazyJob = GlobalScope.launch(start = CoroutineStart.LAZY) {
            //开启一个后台协程
            repeat(3) {
                delay(1000)
                "repeat:${time()}:$it".log()
            }
        }
        Thread.sleep(2500)   //阻塞主线程
        "main thread wait 2.5s:${time()}".log()
        lazyJob.start()
        Thread.sleep(2500)   //阻塞主线程
        "main thread end:${time()}".log()
        /*  打印结果
            _协程_2.kt:main2:41->: main thread wait 2.5s
            _协程_2.kt:invokeSuspend:37->: repeat:0
            _协程_2.kt:invokeSuspend:37->: repeat:1
            _协程_2.kt:main2:44->: main thread end
         */
    }


    @Test
    fun runBlocking() {
        //runBlocking 会阻塞主线程
        val lazyJob = GlobalScope.launch(start = CoroutineStart.LAZY) {
            //开启一个后台协程
            repeat(3) {
                delay(1000)
                "repeat:${time()}:$it".log()
            }
        }
        runBlocking {
            "runBlocking:${time()}".log()
            delay(2500)
        }   //阻塞主线程
        "main thread wait 2.5s:${time()}".log()
        lazyJob.start()
        runBlocking {
            "runBlocking2:${time()}".log()
            delay(2500)
        }     //阻塞主线程
        "main thread end:${time()}".log()
        /*  打印结果
            _协程_2.kt:invokeSuspend:101->: runBlocking:27:04:55
            _协程_2.kt:invokeSuspend:97->: repeat:27:05:108:0
            _协程_2.kt:invokeSuspend:97->: repeat:27:06:114:1
            _协程_2.kt:invokeSuspend:97->: repeat:27:07:126:2
            _协程_2.kt:runBlocking2:105->: main thread end:27:07:134
         */
    }


    @Test
    fun runBlocking2() {
        //CoroutineStart.LAZY  不会开始执行
        val lazyJob = GlobalScope.launch(start = CoroutineStart.LAZY) {
            //开启一个后台协程
            repeat(3) {
                delay(1000)
                "repeat:${time()}:$it".log()
            }
        }
        runBlocking {
            "runBlocking:${time()}".log()
//            lazyJob.start()
            lazyJob.join()//如果是LAZY join自带开启效果 runBlocking 等待lazyJob任务执行完成
        }   //阻塞主线程
        "main thread end:${time()}".log()
        /*  打印结果
            _协程_2.kt:main2:41->: main thread wait 2.5s
            _协程_2.kt:invokeSuspend:37->: repeat:0
            _协程_2.kt:invokeSuspend:37->: repeat:1
            _协程_2.kt:main2:44->: main thread end
         */
    }


    @Test
    fun runBlocking3() {
        runBlocking {
            "runBlocking:${time()}".log()
            //TODO 与GlobalScope.launch不同,launch开启的是子任务 runBlocking会等待所有子任务执行结束
            val launch = launch(start = CoroutineStart.LAZY) {
                "launch--------------".log()
                repeat(3) {
                    delay(1000)
                    "repeat:$isActive:${time()}:$it".log()
                }
            }
            //TODO runBlocking的LAZY子任务 如果不启动 runBlocking一直阻塞
//            launch.join() //会堵塞 runBlocking
            launch{
                delay(2500)
                launch.cancel()
            }
            launch.join()
            "launch.cancelAndJoin()".log()
            launch.cancelAndJoin() //取消任务

        }   //阻塞主线程
        "main thread end:${time()}".log()
        /*  打印结果
            _协程_2.kt:invokeSuspend:118->: runBlocking:26:33:711
            _协程_2.kt:invokeSuspend:122->: repeat:26:34:776:0
            _协程_2.kt:invokeSuspend:122->: repeat:26:35:777:1
            _协程_2.kt:invokeSuspend:122->: repeat:26:36:779:2
            _协程_2.kt:runBlocking3:130->: main thread end:26:36:791
         */
    }

    @Test
    fun coroutine() = runBlocking {
//        runBlocking {
            //会阻塞runBlocking
            launch {
                //不会阻塞 runBlocking
                delay(200L)
                println("runBlocking launch")
            }
            println("runBlocking end 1")
//        }

        coroutineScope {
            //会阻塞 runBlocking
            launch {
                delay(100L)
                println("coroutineScope launch")
            }
            delay(100L)
            println("coroutineScope")
        }
        println("runBlocking end 2")
        /*  打印结果
       _协程_2.kt:invokeSuspend:118->: runBlocking:26:33:711
       _协程_2.kt:invokeSuspend:122->: repeat:26:34:776:0
       _协程_2.kt:invokeSuspend:122->: repeat:26:35:777:1
       _协程_2.kt:invokeSuspend:122->: repeat:26:36:779:2
       _协程_2.kt:runBlocking3:130->: main thread end:26:36:791
    */
    }


    @Test
    fun coroutine2() {
        GlobalScope.launch {
            runBlocking {
                //会阻塞runBlocking
                launch {
                    //不会阻塞 runBlocking
                    delay(200L)
                    println("runBlocking launch")
                }.join()
                println("runBlocking")
            }
            println("runBlocking end 1")
            coroutineScope {
                //会阻塞 runBlocking
                launch {
                    delay(100L)
                    println("coroutineScope launch")
                }.join()
                println("coroutineScope")
            }
            println("runBlocking end 2")
            /*  打印结果
                runBlocking launch
                runBlocking
                runBlocking end 1
                coroutineScope launch
                coroutineScope
                runBlocking end 2
                main end
        */
        }
        Thread.sleep(4000L)
        println("main end")
    }

    @Test
    fun timeOut() = runBlocking<Unit> {
        val withTimeout = withTimeout(2000) {
            //withTimeout 超时会抛异常
            repeat(3) {
                delay(500)
                "repeat:$it".log()
            }
            "withTimeout end"
        }

        val withTimeoutOrNull = withTimeoutOrNull(2000) {
            //withTimeout 超时返回空值
            //超时会抛异常
            repeat(3) {
                delay(500)
                "repeat:$it".log()
            }
            "withTimeoutOrNull end"
        }
        "$withTimeout -- runBlocking end".log()
        "$withTimeoutOrNull --  runBlocking end".log()
    }


    @Test
    fun timeOut2() = runBlocking<Unit> {
        val launch = launch {
            try {
                repeat(5) {
                    delay(1000)
                    "repeat$it".log()
                }
            } finally {
                "cancelAndJoin".log()
                withContext(NonCancellable) {
                    //不可取消的任务
                    delay(1000)
                    "NonCancellable".log()
                }
            }
        }
        delay(3000)
        launch.cancelAndJoin()
        "runBlocking end".log()
    }

}

fun time(): String {
    val dateFormat = SimpleDateFormat("mm:ss:SS")
    return dateFormat.format(System.currentTimeMillis())
}